package com.nsoft.html5npub.business;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Toast;

import com.nsoft.html5npub.objects.BookItem;
import com.nsoft.html5npub.objects.Settings;
import com.nsoft.html5npub.utils.Constant;
import com.nsoft.html5npub.utils.utils;

/**
 * <b>
 * 
 * @author minhld
 *
 */
public class BookDownloader extends 
			AsyncTask<Void,Integer,Void>{
	
	final int DOWNLOAD_DELETEFOLDER_FAILED=-100;
	final int DOWNLOAD_CONNECTION_FAILED=-101;
	final int DOWNLOAD_STREAM_UNAVAILABLE=-102;
	final int DOWNLOAD_SUCCESSFULLY=150;
	final int DOWNLOAD_EXTRACT_ZIPFILE=151;
	final int DOWNLOAD_SAVETO_DATABASE=152;
	
	private Context context;
	private ArrayAdapter<BookItem> adapter;
	private ProgressDialog progressor=null;
	private BookItem book=null;
	private int pos;
	
	public BookDownloader(Context ctx,
			ArrayAdapter<BookItem> _adapter,	
			BookItem _book,int _pos){
		this.context=ctx;
		this.progressor=new ProgressDialog(ctx);
		this.adapter=_adapter;
		this.book=_book;
		this.pos=_pos;
	}
	
	@Override
	protected void onPreExecute(){
		progressor.setCancelable(true);
		progressor.setMessage(Constant.
				booklist.BLF_FILE_DOWNLOADING);
		progressor.setProgressStyle(
				ProgressDialog.STYLE_HORIZONTAL);
		progressor.setProgress(0);
		progressor.setMax(100);
		progressor.setProgress(0);
		progressor.show();
	}
	
	@Override
	protected Void doInBackground(Void... params){
		InputStream input=null;
		OutputStream output=null;
		String outPath=utils.getBookPath();
		String oldBookPath=outPath+
				Constant.PATH_SPLITTER+
				this.book.getContentName();
		
		File oldBookPathFile=new File(oldBookPath);
		if (oldBookPathFile.exists()){
			try{
				utils.delete(oldBookPathFile);
			}catch(IOException e){
				Log.e("BookDownloader.deleteFolder()",
					e.getClass()+": "+e.getMessage());
				publishProgress(DOWNLOAD_DELETEFOLDER_FAILED);
				return null;
			}
		}
				
		try{
			String urlBookPath=book.getDownloadPath();
			URL url=new URL(urlBookPath);
			String fileName=urlBookPath.substring(
					urlBookPath.lastIndexOf(
							Constant.PATH_SPLITTER)+1);
			String outputFilePath=outPath+
					Constant.PATH_SPLITTER+fileName;
			
			HttpURLConnection connection=
	        		(HttpURLConnection)url.openConnection();
	        connection.setDoInput(true);
	        connection.setConnectTimeout(
	        		Constant.dataserver.
	        			SERVER_CONNECT_TIMEOUT);
	        connection.connect();
	        
	        int retCode=connection.getResponseCode();
	        if (retCode==Constant.dataserver.SERVER_CODE_OK){
	        	input=connection.getInputStream();
	        }else{
	        	Log.e("BookDownloader.connect()",
	        			Constant.dataserver.
	        			ERROR_RESPONSE_INCORRECT.replace(
	        					Constant.CHR_REPLACE, 
	        					Integer.toString(retCode)));
	        	publishProgress(DOWNLOAD_CONNECTION_FAILED);
	        	return null;
	        }
	        
	        output=new FileOutputStream(outputFilePath,false);
	        
	        int totalBytesRead=0;
	        int estimateBytes=connection.getContentLength();
	        byte[] buff=new byte[1024];
	        int bytesRead=0;
	        while((bytesRead=input.read(buff))!=-1){
	        	output.write(buff,0,bytesRead);
	        	totalBytesRead+=bytesRead;
	        	
	        	publishProgress((int)
	        		(((double)totalBytesRead/
        				(double)estimateBytes)*
	        					(double)100));
	        }
	        output.flush();
	        output.close();
	        
	        /**
	         * extract the ZIP file
	         */
	        publishProgress(DOWNLOAD_EXTRACT_ZIPFILE);
	        utils.unzipFile(context,
	        		outputFilePath,outPath,true);
	        utils.delete(new File(outputFilePath));
	        
	        /**
	         * copy the java-script supplier file
	         */
	        String jsFolder=outPath+
	        		Constant.PATH_SPLITTER+
	        		this.book.getContentName();
	        try{
	        	utils.copySupplierJs(context,jsFolder);
	        }catch(Exception e){
	        	Log.e("BookDownloader.copySupplierJs()",
	        			e.getClass()+": "+e.getMessage());
	        }
	        
	        /**
	         * save to database
	         */
	        publishProgress(DOWNLOAD_SAVETO_DATABASE);
	        this.book.setDownloaded(Constant.DOWNLOADED_TRUE);
	        dbengine.updateBook(this.book);
	        
	        publishProgress(DOWNLOAD_SUCCESSFULLY);
			return null;
		}catch(IOException e){
			Log.e("BookDownloader.doInBackground()",
		    	e.getClass().toString()+": "+e.getMessage());
			publishProgress(DOWNLOAD_CONNECTION_FAILED);
		}finally{
			try {
				if (input!=null){
					input.close();
				}
				/*
				if (output!=null){
					output.close();
				}
				*/
			}catch(IOException e){ }
		}
		
		return null;
	}
	
	@Override
	protected void onProgressUpdate(Integer... values) {
		if (values[0]==DOWNLOAD_DELETEFOLDER_FAILED){
			utils.showError(context,
				Constant.DIALOG_ERROR,
				Constant.booklist.
					BLF_ERROR_DELETE_FOLDER_FAILED);
		}else if (values[0]==DOWNLOAD_CONNECTION_FAILED){
			utils.showError(context,
				Constant.DIALOG_ERROR,
				Constant.booklist.
					BLF_ERROR_DOWNLOADING_FAILED);
		}else if (values[0]==DOWNLOAD_STREAM_UNAVAILABLE){
			utils.showError(context,
				Constant.DIALOG_ERROR,
				Constant.dataserver.
					ERROR_RESPONSE_STREAM_UNAVAILABLE);
		}else if (values[0]>=0&&values[0]<=100){
			progressor.setProgress(values[0]);
			return;
		}else if (values[0]==DOWNLOAD_SUCCESSFULLY){
			Toast.makeText(context,
					Constant.booklist.BLF_DOWNLOAD_DONE,
					Toast.LENGTH_SHORT).show();
			if (Settings.isVibrationOn()){
				utils.vibrate(BookDownloader.this.context,50);
			}
			/**
			 * update the book list
			 */
			refreshBook(this.book,this.pos);
		}else if (values[0]==DOWNLOAD_EXTRACT_ZIPFILE){
			progressor.setMessage(Constant.booklist.
					ELF_DOWNLOAD_EXTRACTING);
			return;
		}else if (values[0]==DOWNLOAD_SAVETO_DATABASE){
			progressor.setMessage(Constant.booklist.
					ELF_DOWNLOAD_SAVETO_DB);
			return;
		}else{
			/*return;*/
		}
		progressor.dismiss();
	}
	
	private void refreshBook(BookItem book,int pos){
		BookItem newBook=book;
		this.adapter.remove(book);
		newBook.setDownloaded(Boolean.TRUE.
				toString().toLowerCase());
		this.adapter.insert(newBook,pos);
		this.adapter.notifyDataSetChanged();
	}
	
}
